<template>
  <el-tabs v-model="activeTab" tab-position="left" type="border-card" class="batch-import-tabs">
    <el-tab-pane :name="index" v-for="(item, index) in formTableList" :key="index"
    >
      <template #label>
        <el-tooltip effect="light" :content="item.title">
          <div class="batch-import-tabs-label">
            {{ item.title }}
            <el-icon class="warning-icon" size="24" color="#f56c6c" v-if="item.errorList.length"><WarningFilled /></el-icon>
          </div>
        </el-tooltip>
      </template>
      <VFormTable 
        :columns="item.columns" 
        :data="item.data" 
        :errorList="item.errorList" 
        :allErrorNumber="allErrorNumber"
        @validate="onValidate"
        @field-change="onFieldChange"
        @rows-remove="onRowsRemove"
        @all-row-remove="onAllRowRemove" />
    </el-tab-pane>
  </el-tabs>
</template>
<script>
const commonRegExpTips = {
  number: '包含非数字字符',
  letter: '包含非字母字符',
  letterAndNumber: '只能输入字母或数字',
  mobilePhone: '手机号码格式有误',
  letterStartNumberIncluded: '必须以字母开头，可包含数字',
  noChinese: '不可输入中文字符',
  chinese: '只能输入中文字符',
  email: '邮箱格式有误',
  url: 'URL格式有误',
  noPercent: '不能输入%',
}
import dayjs from 'dayjs'
import { getFormViewData } from '@/api/formtemplate/index'
import VFormTable from '@/components//form-table/index.vue'
import { defineAsyncComponent } from 'vue'
import i18n from '@/utils/i18n'
import { deepClone, evalFn } from '@/utils/util'
import { getRegExp } from '@/utils/validators.js'
export default {
  mixins: [i18n],
  components: {
    VFormRender: defineAsyncComponent(() => import('@/components/form-render/index.vue')),
    VFormTable,
  },
  props: {
    widget: Object,
    formTemp: Object,
    formId: String,
    bookId: String,
    recordId: String,
    subFormId: String,
    tableObj: Object,
  },
  data() {
    return {
      activeTab: 0,
      formTableList: [],
      loading: true,
    }
  },
  computed: {
    allErrorNumber() {
      return this.formTableList.reduce((total, item) => {
        return total + item.errorList.length
      }, 0)
    }
  },
  watch: {
    tableObj: {
      handler(val) {
        if(Object.keys(val.tableList).length) {
          this.generatorFormTable(this.formTemp)
        } else {
          this.formTableList = []
        }
      }
    }
  },
  methods: {
    /**
     * 生成表单数据列表
     * 
     * @param {Object} sourceFormTemp - 源表单模板，包含表单数据域
     * @returns {void} 
     * 
     * 该方法根据传入的源表单模板生成表单数据列表。它会遍历当前组件的表格列表，提取每个表格的列信息，并根据列的定义填充数据。 
     * 如果某个字段为空，则会初始化为默认值，并检查错误状态，记录错误信息。
     * 最终生成的表单数据列表将被赋值给组件的 `formTableList` 属性。
     */
    generatorFormTable (sourceFormTemp) {
      try {
        let formTableList = []
        const tableList = deepClone(this.tableObj.tableList)
        const tableColumns = deepClone(this.tableObj.tableColumns)
        for(let key in tableList) {
          const item = tableList[key]
          if (item.length === 0) continue
          const columns = tableColumns[key === 'main' ? '主表' : item[0].zhlx_gjz_component_label].map(field => {
              if (field.includes('unique-')) {
                let column = sourceFormTemp.formDataDomain.find(domain => domain.options.name === field.replace('unique-', ''))
                column = deepClone(column)
                column.options.name = field
                return column
              }
              if (key === 'main') {
                return sourceFormTemp.formDataDomain.find(domain => domain.options.name === field)
              }
              return sourceFormTemp.formDataDomain.find(widget => widget.options.name === key)?.widgetList.find(domain => domain.options.name === field)
            })
          const errorList = []
          const formTableListItem = {
            key,
            title: key === 'main' ? '主表' : item[0].zhlx_gjz_component_label,
            sourceData: item,
            columns,
            data: (key === 'main' ? item : item.map(values => values.zhlx_gjz_subform_value)).map((row, index) => {
              Object.keys(row).forEach(colId => {
                const widget = columns.find(domain => domain.options.name === colId)
                if(!row[colId] || !row[colId][0]) {
                  row[colId] =  [
                    {
                      "zhlx_gjz_id": "",
                      "zhlx_gjz_label": "",
                      "zhlx_gjz_sortOrder": 0,
                      "zhlx_gjz_component_type": widget?.type,
                      "zhlx_gjz_component_label": widget?.options?.label,
                      "defaultValue": widget?.options?.multiple ? [] : "",
                    }
                  ]
                }
                // 处理数据如果下拉选相关控件返回defaultValue是{}则处理成''
                if(['select', 'select-person', 'select-group', 'select-department', 'select-role', 'select-post', 'select-relativePost'].includes(widget.type) && !widget.options.multiple && JSON.stringify(row[colId][0].defaultValue) === '{}') {
                  row[colId][0].defaultValue = ''
                }
                // 如果数据时时间和时间范围控件并valueFormat = x；则将defaultvalue值更新为数值类型
                if(['date', 'date-range'].includes(widget.type) && widget.options.valueFormat === 'x') {
                  const value = row[colId][0].defaultValue
                  if (['date'].includes(widget.type) && row[colId][0].defaultValue) {
                    row[colId][0].defaultValue = row[colId][0].defaultValue * 1
                  } else if (['date-range'].includes(widget.type) && row[colId][0].defaultValue?.length) {
                    row[colId][0].defaultValue = row[colId][0].defaultValue.map(item => item * 1)
                  }
                }

                // 如果是select类型、checkbox类型、radio类型
                if (['select', 'checkbox', 'radio'].includes(widget.type)) {
                  let multiple = false
                  if (['checkbox'].includes(widget.type) || widget.options.multiple) {
                    multiple = true
                  }
                  const valueItemList = multiple ? (row[colId][0].defaultValue || []) : (row[colId][0].defaultValue ? [row[colId][0].defaultValue] : [])
                  const optionItems = widget.options.optionItems
                  const newValueItemList = valueItemList.map(val => {
                    const optionItem = optionItems.find(option => option.value == val)
                    if (optionItem?.value) {
                      return ['select'].includes(widget.type) ? optionItem.value?.toString() : optionItem.value
                    }
                    return val
                  })
                  row[colId][0].defaultValue = multiple ? newValueItemList : (newValueItemList[0] || '')
                }

                const statusObj = this.getErrorStatus(widget, row[colId])
                if (statusObj !== false) {
                  errorList.push({...statusObj, index})
                  row[colId][0].errorMessage = statusObj.message
                }
                // 后端未处理multiple时，将defaultValue值更新为数组类型 --已废弃
                // if(widget.options.multiple && !Array.isArray(row[colId][0].defaultValue)) {
                //   row[colId][0].defaultValue = [row[colId][0].defaultValue]
                // }
              })
              row.index = index
              return row
            })
          }
          
          formTableList.push({
            ...formTableListItem,
            errorList
          })
        }
        this.formTableList = formTableList
        // console.log('formTableList', formTableList)
      } catch (error) {
        console.error('【generatorFormTable方法异常】', error)
      }
    },
    /**
     * 验证指定列和行的数据有效性，并更新错误列表。
     * 
     * @param {Object} column - 当前列的对象，包含列的相关信息。
     * @param {Object} row - 当前行的数据对象，包含行的相关信息。
     * 
     * 如果数据有效，则从错误列表中移除相应的错误信息；如果数据无效，则将错误信息添加到错误列表中。
     */
    onValidate (column, row) {
      const curRow = this.formTableList[this.activeTab].data.find(item => item.index === row.index)
      const res = this.getErrorStatus(column, curRow[column.options.name])
      const index = this.formTableList[this.activeTab].errorList.findIndex(item => item.id === column.options.name && item.index === row.index)
        if (res === false) {
          if (index !== -1) {
            this.formTableList[this.activeTab].errorList.splice(index, 1)
            delete curRow[column.options.name][0].errorMessage
          }
        } else {
          if (index === -1) {
            this.formTableList[this.activeTab].errorList.push({ ...res, index: row.index })
            curRow[column.options.name][0].errorMessage = res.message
          }
      }
    },
    /**
     * 处理字段变化事件，根据不同的条件更新表单数据。
     * 
     * @param {Object} column - 当前字段的列信息。
     * @param {Object} row - 当前行的数据。
     * @param {boolean} batchEdit - 是否为批量编辑模式。
     * 
     * 在批量编辑模式下，遍历所有行，根据字段类型和旧值判断是否需要更新新值。
     * 支持的字段类型包括：select-department, select-group, select-role, select-person, select-post, select-relativePost, select, checkbox。
     * 
     * 如果不是批量编辑模式，则直接更新当前行的字段值。
     */
    onFieldChange (column, row, batchEdit) {
      const curRow = this.formTableList[this.activeTab].data.find(item => item.index === row.index)
      const oldDefaultValue = curRow[column.options.name][0].defaultValue
      const newDefaultValue = row[column.options.name][0].defaultValue
      if (batchEdit) {
        this.formTableList[this.activeTab].data.forEach((item, index) => {
          if (['select-department', 'select-group', 'select-role', 'select-person', 'select-post', 'select-relativePost'].includes(column.type)) {
            if (column.options.multiple) {
              const oldDefaultValueMainIds = oldDefaultValue.map(colItem => colItem.mainId)
              const filterDefaultValue = item[column.options.name][0].defaultValue.filter(colItem => oldDefaultValueMainIds.includes(colItem.mainId))
              if (filterDefaultValue.length === item[column.options.name][0].defaultValue.length) {
                this.updateFieldValue(column, item, newDefaultValue)
              }
            } else {
              if (item[column.options.name][0].defaultValue.mainId === oldDefaultValue.mainId) {
                this.updateFieldValue(column, item, newDefaultValue)
              }
            }
          } else if (['select', 'checkbox'].includes(column.type)) {
            if (column.options.multiple || ['checkbox'].includes(column.type)) {
              if (JSON.stringify(item[column.options.name][0].defaultValue) === JSON.stringify(oldDefaultValue)) {
                this.updateFieldValue(column, item, newDefaultValue)
              }
            } else {
              if (item[column.options.name][0].defaultValue === oldDefaultValue) {
                this.updateFieldValue(column, item, newDefaultValue)
              }
            }
          } else {
            if(JSON.stringify(item[column.options.name][0].defaultValue) === JSON.stringify(oldDefaultValue)) {
              this.updateFieldValue(column, item, newDefaultValue)
            }
          }
        })
      } else {
        this.updateFieldValue(column, row, newDefaultValue)
      }
    },
    onRowsRemove(rows) {
      rows.forEach(item => {
        const i = this.formTableList[this.activeTab].data.findIndex(t => t.index === item.index)
        this.formTableList[this.activeTab].data.splice(i, 1)
        this.formTableList[this.activeTab].errorList = this.formTableList[this.activeTab].errorList.filter(errItem => errItem.index !== item.index)
      })
    },
    onAllRowRemove() {
      this.formTableList[this.activeTab].data = []
      this.formTableList[this.activeTab].errorList = []
    },
    /**
     * 更新指定列和行的字段值。
     * 根据列的类型，更新表单数据中的相应字段，包括默认值、ID和标签等信息。
     * 支持的列类型包括：输入框、文本区域、数字、时间、开关、评分、滑块、序列号、日期、时间范围、日期范围、单选框、复选框、下拉选择、部门选择、角色选择等。
     * 
     * @param {Object} column - 列的配置对象，包含类型和选项等信息。
     * @param {Object} row - 行的对象，包含行索引等信息。
     * @param {any} value - 要更新的值，可以是字符串、数组或对象，具体取决于列的类型。
     */
    updateFieldValue (column, row, value) {
      const curRow = this.formTableList[this.activeTab].data.find(item => item.index === row.index)
      if (['input', 'textarea', 'time', 'switch', 'rate', 'slider', 'serial-number'].includes(column.type)) {
        Object.assign(curRow[column.options.name][0], {
          defaultValue: value || "",
          zhlx_gjz_id: value || "",
          zhlx_gjz_label: value || "",
        })
      } else if (['number'].includes(column.type)) {
        const valueNumber = value ? Number(value) : ""
        Object.assign(curRow[column.options.name][0], {
          defaultValue: valueNumber,
          zhlx_gjz_id: valueNumber,
          zhlx_gjz_label: valueNumber,
        })
      } else if(['date'].includes(column.type)) {
        const formatValue = value ? this.handlerDateFormat(value, column.options.format) : ''
        const valueFormatValue = value ? this.handlerDateFormat(value, column.options.valueFormat) : ''
        Object.assign(curRow[column.options.name][0], {
          defaultValue: valueFormatValue || '',
          zhlx_gjz_id: valueFormatValue || '',
          zhlx_gjz_label: formatValue || '',
        })
      } else if(['time-range'].includes(column.type)) {
        const joinStr = value?.length ? value.join('~') : ""
        Object.assign(curRow[column.options.name][0], {
          defaultValue: value || [],
          zhlx_gjz_id:  joinStr,
          zhlx_gjz_label: joinStr,
        })
      } else if(['date-range'].includes(column.type)) {
        const formatValue = value?.length ? value.map(item => this.handlerDateFormat(item, column.options.format)) : []
        const valueFormatValue = value?.length ? value.map(item => this.handlerDateFormat(item, column.options.valueFormat)) : []
        Object.assign(curRow[column.options.name][0], {
          defaultValue: valueFormatValue,
          zhlx_gjz_id:  valueFormatValue.join('~'),
          zhlx_gjz_label: formatValue.join('~'),
        })
      } else if (['radio'].includes(column.type) || (['select'].includes(column.type) && !column.options.multiple)) {
        const optionItems = column.options.optionItems
        Object.assign(curRow[column.options.name][0], {
          defaultValue: value,
          zhlx_gjz_id: value,
          zhlx_gjz_label: optionItems.find(option => option.value == value)?.label
        })
      } else if (['checkbox'].includes(column.type) || (['select'].includes(column.type) && column.options.multiple)) {
        if (!value?.length) {
          curRow[column.options.name] = [{
            defaultValue: [],
            zhlx_gjz_id: "",
            zhlx_gjz_label: "",
            zhlx_gjz_sortOrder: 0,
            zhlx_gjz_component_type: column.type,
            zhlx_gjz_component_label: column.options.label,
          }]
        } else {
          const optionItems = column.options.optionItems
          curRow[column.options.name] = value.map((item, index) => {
            const returnItem = {
              zhlx_gjz_id: item,
              zhlx_gjz_label: optionItems.find(option => option.value == item)?.label,
              zhlx_gjz_sortOrder: 0,
              zhlx_gjz_component_type: column.type,
              zhlx_gjz_component_label: column.options.label,
            }
            if (index === 0) {
              returnItem.defaultValue = value
            }
            return returnItem
          })
        }
        
      } else if (['select-department', 'select-group', 'select-role', 'select-person', 'select-post', 'select-relativePost'].includes(column.type)) {
        if(column.options.multiple) {
          if (value.length) {
            curRow[column.options.name] = value.map((item, index) => {
              const returnItem = {
                zhlx_gjz_id: item.mainId,
                zhlx_gjz_label: item.mainName,
                zhlx_gjz_sortOrder: 0,
                zhlx_gjz_component_type: column.type,
                zhlx_gjz_component_label: column.options.label,
                objectType: item.objectType,
                tenantId: item.tenantId
              }
              if (index === 0) {
                returnItem.defaultValue = value
              }
              return returnItem
            })
          } else {
            curRow[column.options.name] = [{
              zhlx_gjz_id: '',
              zhlx_gjz_label: '',
              zhlx_gjz_sortOrder: 0,
              zhlx_gjz_component_type: column.type,
              zhlx_gjz_component_label: column.options.label,
              objectType: '',
              tenantId: '',
              defaultValue: []
            }]
          }
        } else {
          Object.assign(curRow[column.options.name][0], {
            defaultValue: value ? value : '',
            zhlx_gjz_id: value ? value.mainId : '',
            zhlx_gjz_label: value ? value.mainName : '',
            objectType: value ? value.objectType : '',
            tenantId: value ? value.tenantId : ''
          })
        }
      } else {
        this.$message.error('未知的组件类型，无法修改数据')
      }
      this.onValidate(column, row)
    },
    // 转换日期格式方法
    handlerDateFormat(value, format) {
      if (format === 'x') {
        return dayjs(value).valueOf()
      } else {
        return dayjs(value).format(format)
      }
    },
    getErrorStatus(column, col) {
      const value = col[0].defaultValue
      if (!value || (Array.isArray(value) && !value.length) || JSON.stringify(value) === '{}') {
        if(column.options.required) {
          col[0].errorMessage = '必填项不能为空'
          return {
            id: column.options.name,
            message: '必填项不能为空',
          }
        }
        return false
      }
      const validation = column.options.validation?.replace(/^\s*|\s*$/g,"")
      if (validation && ['input', 'number', 'textarea'].includes(column.type)) {
        const reg = evalFn(getRegExp(validation))
        if (reg && !reg.test(value)) {
          col[0].errorMessage = commonRegExpTips[column.options.validation]
          return {
            id: column.options.name,
            message: commonRegExpTips[column.options.validation],
          }
        }
      }
      if (['rate', 'slider'].includes(column.type)) {
        const max = column.options.max
        const step = column.options.step || 1
        const options = Array.from({length: max / step}, (item, index) => (index + 1) * step)
        if (!options.includes(value)) {
          return {
            id: column.options.name,
            message: '非合规数据',
          }
        }
      }
      return false
    },
  }
}
</script>
<style lang="scss" scoped>
:deep(.isDocumentFrom) {
  padding: 0;
}
.check-container {
  height: 100%;
  border: 1px solid #EBEEF5;
  .check-menu {
    --el-menu-bg-color: #EBEEF5;
    --el-menu-active-color: #000000;
    --el-menu-active-bgcolor: #ffffff;
    height: 100%;
    border-right: none;
    .is-active {
      background-color: var(--el-menu-active-bgcolor);
    }
  }
}
.batch-import-tabs {
  height: 100%;
  :deep(.el-tabs__content) {
    overflow-y: auto;
    padding-bottom: 0;
    height: 100%;
  }
  :deep(.el-main) {
    padding: 0;
  }
  :deep(.el-tab-pane) {
    height: 100%;
  }
  .batch-import-tabs-label {
    width: 200px;
    // 溢出隐藏并显示省略号
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  :deep(.el-tabs__nav) {
    .el-tabs__item {
      position: relative;
      text-align: center;
      justify-content: center;
      .warning-icon {
        position: absolute;
        right: 4px;
        top: 50%;
        transform: translateY(-50%);
      }
    }
  }
}
</style>